
#include <assert.h>
#include "utility.h"
#include "qr-const.h"

int qr_check_version(int version)
{
	int result;

	if(version >= QR_VERSION_MIN && version <= QR_VERSION_MAX)
	{
		result = 0;
	}
	else
	{
		result = -1;
	}
	return result;
}

int qr_check_mode(QRMode mode)
{
	int result;

	if(mode > QR_MODE_INVALID && mode < QR_MODE_COUNT)
	{
		result = 0;
	}
	else
	{
		result = -1;
	}
	return result;
}

int qr_check_ec_level(ECLevel ec_level)
{
	int result;

	if(ec_level > EC_LEVEL_INVALID && ec_level < EC_LEVEL_COUNT)
	{
		result = 0;
	}
	else
	{
		result = -1;
	}
	return result;
}

int qr_check_mask_pattern(MaskPattern mask_pattern)
{
	int result;

	if(mask_pattern > MASK_PATTERN_INVALID && mask_pattern < MASK_PATTERN_COUNT)
	{
		result = 0;
	}
	else
	{
		result = -1;
	}
	return result;
}

int qr_character_count_indicator(int version, QRMode mode)
{
	int index;

	if(qr_check_version(version) < 0 || qr_check_mode(mode) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	if(version <= 9)
	{
		index = 0;
	}
	else if(version <= 26)
	{
		index = 1;
	}
	else
	{
		index = 2;
	}
	return characterCountIndicatorLengthTable[index][mode];
}

int qr_data_words_count(int version, ECLevel ec_level)
{
	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	return qrCapacity[version]._words - qrCapacity[version]._ec_words[ec_level];
}

int qr_ec_words_count(int version, ECLevel ec_level)
{
	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	return qrCapacity[version]._ec_words[ec_level];
}

int qr_remainder_count(int version)
{
	if(qr_check_version(version) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	return qrCapacity[version]._remainder;
}

int qr_ecc_block_count1(int version, ECLevel ec_level)
{
	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	return eccTable[version][ec_level][0];
}

int qr_ecc_block_count2(int version, ECLevel ec_level)
{
	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	return eccTable[version][ec_level][1];
}

int qr_ecc_data_length1(int version, ECLevel ec_level)
{
	int data_words;
	int block_count1;
	int block_count2;

	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	data_words = qr_data_words_count(version, ec_level);
	if(data_words < 0)
	{
		RES_INVAL("Invoke qr_data_words_count error.");
	}
	block_count1 = qr_ecc_block_count1(version, ec_level);
	if(block_count1 <= 0)
	{
		RES_INVAL("Invoke qr_ecc_block_count1 error.");
	}
	block_count2 = qr_ecc_block_count2(version, ec_level);
	if(block_count2 < 0)
	{
		RES_INVAL("Invoke qr_ecc_block_count2 error.");
	}
	return data_words / (block_count1 + block_count2);
}

int qr_ecc_data_length2(int version, ECLevel ec_level)
{
	int block_count2;
	int result;

	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	block_count2 = qr_ecc_block_count2(version, ec_level);
	if(block_count2 < 0)
	{
		RES_INVAL("Invoke qr_ecc_block_count2 error.");
	}
	if(0 == block_count2)
	{
		result = 0;
	}
	else
	{
		result = qr_ecc_data_length1(version, ec_level);
		if(result < 0)
		{
			RES_INVAL("Invoke qr_ecc_data_length1 error.");
		}
		++result;
	}
	return result;
}

int qr_ecc_ecc_length(int version, ECLevel ec_level)
{
	int ec_words;
	int block_count1;
	int block_count2;

	if(qr_check_version(version) < 0 || qr_check_ec_level(ec_level) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	ec_words = qr_ec_words_count(version, ec_level);
	if(ec_words < 0)
	{
		RES_INVAL("Invoke qr_ec_words_count error.");
	}
	block_count1 = qr_ecc_block_count1(version, ec_level);
	if(block_count1 <= 0)
	{
		RES_INVAL("Invoke qr_ecc_block_count1 error.");
	}
	block_count2 = qr_ecc_block_count2(version, ec_level);
	if(block_count2 < 0)
	{
		RES_INVAL("Invoke qr_ecc_block_count2 error.");
	}
	return ec_words / (block_count1 + block_count2);
}

int qr_width(int version)
{
	int width;

	if(qr_check_version(version) < 0)
	{
		RES_INVAL("Argument is invalid.");
	}

	width = ((version - 1) << 2) + QR_WIDTH_MIN;
	assert(width >= QR_WIDTH_MIN && width <= QR_WIDTH_MAX);
	return width;
}

unsigned int qr_format_information(ECLevel ec_level, MaskPattern mask_pattern)
{
	assert(0 == qr_check_ec_level(ec_level) && 0 == qr_check_mask_pattern(mask_pattern));

	return formatInformation[ec_level][mask_pattern];
}

